package com.readboottest.util;


import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.httpclient.protocol.SSLProtocolSocketFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

/**
 * http请求帮助类 - TODO(描述类的职责)
 */
public class HttpUtil {

    public static final String DEFAULT_ENCODING = "UTF-8";
    public static final int SSLPROTOCOL_PORT = 443;

    /**
     * @param url
     * @param params
     * @return
     * @Description 发送https请求
     */
    public static String getHttps(String url, String params) {
        return new String(getBytesHttps(url, params));
    }

    /**
     * 获取byte[]返回
     *
     * @param url
     * @param params
     * @return
     */
    public static byte[] getBytesHttps(String url, String params) {
        // 构造HttpClient的实例
        HttpClient httpClient = new HttpClient();
        // 组装get请求url
        if (params != null) {
            url = url + "?" + params;
        }
        Protocol myhttps = new Protocol("https",
                new SSLProtocolSocketFactory(), SSLPROTOCOL_PORT);
        Protocol.registerProtocol("https", myhttps);
        // 构造getMethod的实例
        GetMethod getMethod = new GetMethod(url);
        // 设置编码格式
        getMethod.getParams().setContentCharset(DEFAULT_ENCODING);
        try {
            // 执行getMethod,调用http接口
            httpClient.executeMethod(getMethod);
            // 读取内容
            byte[] responseBody = getMethod.getResponseBody();
            return responseBody;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 释放连接
            getMethod.releaseConnection();
        }
        return null;
    }

    /**
     * 向指定URL发送GET方法的请求
     *
     * @param url             发送请求的URL
     * @param responseCharset 请求参数，请求参数应该是 json 的形式。
     * @return URL 所代表远程资源的响应结果
     */
    public static String sendGet(String url,
                                 String responseCharset, int timeOut) {
        URL realUrl;
        URLConnection connection = null;
        StringBuilder result = new StringBuilder();
        responseCharset = responseCharset == null ? "UTF-8" : responseCharset;
        try {
            realUrl = new URL(url);
            // 打开和URL之间的连接
            connection = realUrl.openConnection();
            if (connection != null) {
                connection.setConnectTimeout(timeOut);
                connection.setReadTimeout(timeOut);
                // 设置通用的请求属性
                connection.setRequestProperty("accept", "*/*");
                connection.setRequestProperty("connection", "Keep-Alive");
                connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
                connection.setRequestProperty("Content-Type", "application/json");
                // 建立实际的连接
                connection.connect();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        if (connection != null) {
            // 获取所有响应头字段
            // 定义 BufferedReader输入流来读取URL的响应
            try (
                    BufferedReader in = new BufferedReader(new InputStreamReader(
                            connection.getInputStream(), responseCharset))
            ) {
                String line;
                while ((line = in.readLine()) != null) {
                    result.append(line);
                }
            } catch (Exception e) {

            }
        }
        return result.toString();
    }

    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url   发送请求的 URL
     * @param param 请求参数，请求参数应该是 json的形式。
     * @return 所代表远程资源的响应结果
     */
    public static String sendPost(String url, String param,
                                  String responseCharset, int timeOut) {
        URL realUrl;
        URLConnection conn = null;
        StringBuilder result = new StringBuilder();
        responseCharset = responseCharset == null ? "gbk" : responseCharset;
        try {
            realUrl = new URL(url);
            // 打开和URL之间的连接
            conn = realUrl.openConnection();
            if (conn != null) {
                conn.setConnectTimeout(timeOut);
                conn.setReadTimeout(timeOut);
                // 设置通用的请求属性
                conn.setRequestProperty("accept", "*/*");
                conn.setRequestProperty("connection", "Keep-Alive");
//				conn.setRequestProperty("user-agent","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
                conn.setRequestProperty("Content-Type", "application/json");
                // 发送POST请求必须设置如下两行
                conn.setDoOutput(true);
                conn.setDoInput(true);
                conn.connect();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        if (conn != null) {
            try (
                    // 获取URLConnection对象对应的输出流
                    PrintWriter out = new PrintWriter(conn.getOutputStream())
            ) {
                // 发送请求参数
                out.print(param);
                // flush输出流的缓冲
                out.flush();
            } catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
            }

            try (
                    // 定义BufferedReader输入流来读取URL的响应
                    BufferedReader in = new BufferedReader(new InputStreamReader(
                            conn.getInputStream(), responseCharset))
            ) {
                String line;
                while ((line = in.readLine()) != null) {
                    result.append(line);
                }
            } catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
            }
        }
        return result.toString();
    }

    public static String sendPost(String url, String param, int timeOut) {
        return sendPost(url, param, null, timeOut);
    }

    public static String sendPost(String url, String param) {
        return sendPost(url, param, 5000);
    }

    public static String sendGet(String url, int timeOut) {
        return sendGet(url, null, timeOut);
    }

    /**
     * 发送HTTP POST请求, 请求体为XML字符串
     *
     * @param url    请求URL
     * @param xmlStr XML字符串
     * @return 返回的XML字符串
     */
    public static String sendWechatPost(String url, String xmlStr) {

        String responseXml = null;
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        CloseableHttpClient httpClient = httpClientBuilder.build();
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Content-Type", "text/xml");
        StringEntity postEntity = new StringEntity(xmlStr, "UTF-8");
        httpPost.setEntity(postEntity);
        try {
            HttpResponse response = httpClient.execute(httpPost);
            HttpEntity responseEntity = response.getEntity();
            responseXml = EntityUtils.toString(responseEntity, "UTF-8");
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return responseXml;

    }

    /**
     * 获取IP地址
     *
     * @param request
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("eco-x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("x-forwarded-for");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }

        if (ip != null) {
            String[] ipList = ip.split(",");
            ip = ipList[0].trim();
        }

        return ip;
    }

    /**
     * @param request
     * @return
     */
    public static String getReferer(HttpServletRequest request) {
        return request.getHeader("referer");
    }

    /**
     * 模拟form表单的形式 ，上传文件 以输出流的形式把文件写入到url中，然后用输入流来获取url的响应
     *
     * @param url      请求地址 form表单url地址
     * @param filePath 文件在服务器保存路径
     * @return String url的响应信息返回值a
     * @throws IOException
     */
    public static String postMultiData(String url, String filePath, String contentType, String filetype) throws IOException {
        //image/jpeg
        //application/pdf
        String result = null;
        File file = new File(filePath);
        if (!file.exists() || !file.isFile()) {
            throw new IOException("文件不存在");
        }
        URL urlObj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) urlObj.openConnection();
        con.setRequestMethod("POST"); // 设置关键值,以Post方式提交表单，默认get方式
        con.setDoInput(true);
        con.setDoOutput(true);
        con.setUseCaches(false); // post方式不能使用缓存
        // 设置请求头信息
        con.setRequestProperty("Connection", "Keep-Alive");
        con.setRequestProperty("Charset", "UTF-8");
        // 设置边界
        String BOUNDARY = "----------" + System.currentTimeMillis();
        con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
        // 请求正文信息
        // 第一部分：
        StringBuilder sb = new StringBuilder();
        sb.append("--"); // 必须多两道线
        sb.append(BOUNDARY);
        sb.append("\r\n");
        sb.append("Content-Disposition: form-data;name=\"" + filetype + "\";filename=\"" + file.getName() + "\"\r\n");
        sb.append("Content-Type:" + contentType + "\r\n\r\n");
        byte[] head = sb.toString().getBytes("utf-8");


        try (
                DataInputStream in = new DataInputStream(new FileInputStream(file));
                // 获得输出流
                OutputStream out = new DataOutputStream(con.getOutputStream())
        ) {
            // 输出表头
            out.write(head);

            // 文件正文部分
            // 把文件已流文件的方式 推入到url中
            int bytes = 0;
            byte[] bufferOut = new byte[1024];
            while ((bytes = in.read(bufferOut)) != -1) {
                out.write(bufferOut, 0, bytes);
            }

            // 结尾部分
            byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("utf-8");// 定义最后数据分隔线
            out.write(foot);
            out.flush();

        } catch (Exception e) {

        }


        StringBuffer buffer = new StringBuffer();
        try (
                // 定义BufferedReader输入流来读取URL的响应
                BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream()))
        ) {

            String line = null;
            while ((line = reader.readLine()) != null) {
                buffer.append(line);
            }
            if (result == null) {
                result = buffer.toString();
            }
        } catch (IOException e) {
            System.out.println("发送POST请求出现异常！" + e);
            e.printStackTrace();
            throw new IOException("数据读取异常");
        }
        return result;
    }

    /**
     * 跨域请求处理
     *
     * @param response
     */
    public static void domainCross(HttpServletResponse response) {
        response.setHeader("Access-Control-Allow-Origin", "*");
    }
}
